using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Sessionizer.Samples.Model;
using Sessionizer.Samples.Model.Imp;
using Sessionizer.Samples.Sessionized.Rankers;
using Sessionizer.Samples.Sessionized.Rankers.Cheater;
using Sessionizer.Samples.Sessionized.Rankers.Database;
using Sessionizer.Samples.Sessionized.Rankers.InitalOrder;
using Sessionizer.Samples.Sessionized.Rankers.NameLength;
using Sessionizer.Samples.Sessionized.TopBuilder;
using Sessionizer.Tests;
using Sessionizer.Tests.Abstraction;

namespace Sessionizer.Samples.Tests
{
    public abstract class AbstractClient : AbstractTest
    {
        /// <summary>
        ///     Prepare our Unity container
        /// </summary>
        /// <param name="container"></param>
        protected override void FixtureConfigure(IIoCContainerBuilder container)
        {
            base.FixtureConfigure(container);
            //Let's register our ITopBuilder implementation
            //TopBuilder can be ContainerControlled
            container.RegisterType<ITopBuilder, TopBuilder>(LifetimeStyle.Container);

            //Let's register rankers
            //NameLengthRanker can be ContainerControlled
            container.RegisterType<NameLengthRanker>(LifetimeStyle.Container);

            //DatabaseRanker can be ContainerControlled
            container.RegisterType<DatabaseRanker>(LifetimeStyle.Container);

            //DatabaseRanker requires IDatabase. Database can be ContainerControlled
            container.RegisterType<IDatabase, Database>(LifetimeStyle.Container);

            //CheaterRanker can be ContainerControlled
            container.RegisterType<CheaterRanker>(LifetimeStyle.Container);

            //InitalOrderRanker depends on session data and sould NOT be ContainerControlled
            //We can use SessionLifetimeManager if we want to share instance 
            //between all resolutions inside session. Let's do so. (that's optional)
            container.RegisterType<InitalOrderRanker>(LifetimeStyle.Session);

            //ConcreteRankerProvider requires InitalOrderRanker thus it should NOT be ContainerControlled
            //Let's store it inside session (optional)
            container.RegisterType<IRankerProvider, ConcreteRankerProvider>(LifetimeStyle.Session);

            //TopBuilder requires IRankAggregator. Let's add implementation.
            //RankAggregator requires IRankerProvider that is implemented by ConcreteRankerProvider.
            //ConcreteRankerProvider is not ContainerControlled thus RankAggregator should NOT.
            //It will be resolved only once so let's keep default lifetime.
            container.RegisterType<IRankAggregator, RankAggregator>();
        }


        private IEnumerable<ITeam> PrepareTeams()
        {
            yield return new Team("Dagger");
            yield return new Team("Vassel");
            yield return new Team("Unknown Systems");
            yield return new Team("Lagger");
            yield return new Team("Doppler");
            yield return new Team("Yappi");
            yield return new Team("Dove Seven");
        }

        private ITeamCollection Teams()
        {
            return new TeamCollection(PrepareTeams().ToList());
        }

        [Test]
        public void WorksAsExpected()
        {
            ITeamCollection teams = Teams();
            var topCount = new TopCount(5);
            var topBuilder = Container.Resolve<ITopBuilder>();
            ITop top = topBuilder.BuildTop(teams, topCount);
            Assert.AreEqual(5, top.Count());
            Assert.IsTrue(teams.Take(5).SequenceEqual(top.Select(r => r.Team)));
        }
    }
}